﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Massiv
{
    public interface IMatrix
    {
        Int32 this[Int32 i, Int32 j] { get; set;}
        Double Decriment();
    }

    public class Vector : IMatrix
    {
        //число строк матрицы
        protected Int32 iMatrix;
        //число столбцов матрицы
        protected Int32 jMatrix;
        protected Int32[,] masMatrix;

        public Vector(Int32 n, Int32 m)
        {
            iMatrix = n;
            jMatrix = m;
            masMatrix = new Int32[iMatrix,jMatrix];
        }

        public Int32 this[Int32 i, Int32 j]
        {
            set
            {
                if ((i > iMatrix) || (j > jMatrix)) throw new Exception("превышени допустимый диапазон матрицы");
                else masMatrix[i, j] = value;
            }
            get
            {
                if ((i > iMatrix) || (j > jMatrix)) throw new Exception("превышени допустимый диапазон матрицы");
                else return masMatrix[i, j];
            }
        }
        public virtual Double Decriment()
        {
            return Math.Sqrt(Math.Pow(masMatrix[0, 0], 2) + Math.Pow(masMatrix[1, 0], 2));
        }

        public static Double operator *(Vector vec1, Vector vec2)
        {
            return (vec1[0, 0]*vec2[0, 0] + vec1[1, 0]*vec2[1, 0]);
        }

        public static Boolean operator == (Vector vec1, Vector vec2)
        {
            return ((vec1[0, 0] == vec2[0, 0]) && (vec1[1, 0] == vec2[1, 0]));
        }

        public static Boolean operator != (Vector vec1, Vector vec2)
        {
            return ((vec1[0, 0] != vec2[0, 0]) && (vec1[1, 0] != vec2[1, 0]));
        }

        public static explicit operator Double(Vector vec)
        {
            return vec.Decriment();
        }

        public static implicit operator Vector(Int32[,] mas)
        {
            Int32 n = mas.GetLength(0);
            Int32 m = mas.GetLength(1);
            if ((n == 2) && (m == 1))
            {
                Vector temp = new Vector(n, m);
                for (Int32 i = 0; i < n; i++)
                {
                    for (Int32 j = 0; j < m; j++)
                    {
                        temp[i, j] = mas[i, j];
                    }
                }
                    return temp;
            }
            else throw new Exception("передан объект превышающий размеры вектора");
        }

        public override string ToString()
        {
            return String.Format("вектор ({0}, {1})", masMatrix[0, 0], masMatrix[1, 0]);
        }
    }

    public class Matrix : Vector, IMatrix
    {
        public Matrix(Int32 n, Int32 m): base(n, m)
        {
            if (iMatrix != jMatrix) throw new Exception("задана не квадратная матрица");
        }

        public new Int32 this[Int32 i, Int32 j]
        {
            set
            {
                if ((i > iMatrix) || (j > jMatrix)) throw new Exception("превышени допустимый диапазон матрицы");
                else masMatrix[i, j] = value;
            }
            get
            {
                if ((i > iMatrix) || (j > jMatrix)) throw new Exception("превышени допустимый диапазон матрицы");
                else return masMatrix[i, j];
            }
        }

        public override Double Decriment()
        {
            if (iMatrix == 1) return (Double)masMatrix[0, 0];
            if (iMatrix == 2) return (Double)(masMatrix[0, 0] * masMatrix[1, 1] - masMatrix[0, 1] * masMatrix[1, 0]);
            if (iMatrix == 3) return (Double)(masMatrix[0, 0] * (masMatrix[1, 1] * masMatrix[2, 2] - masMatrix[1, 2] * masMatrix[2, 1]) - masMatrix[0, 1] * (masMatrix[1, 0] * masMatrix[2, 2] - masMatrix[2, 0] * masMatrix[1, 2]) + masMatrix[0, 2] * (masMatrix[1, 0] * masMatrix[2, 1] - masMatrix[1, 1] * masMatrix[2, 0]));
            else throw new Exception("превышен ранг 3");
        }

        public static explicit operator Double(Matrix mat)
        {
            return mat.Decriment();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //создание первого вектора 

            Vector vec1 = new Vector(2, 1);
            Console.WriteLine("введите первый вектор:");
            for (Int32 j = 0; j < 1; j++)
            {
                for (Int32 i = 0; i < 2; i++)
                {
                    Console.Write("vec1[{0}, {1}] = ", i, j);
                    vec1[i, j] = Int32.Parse(Console.ReadLine());
                }
            }
            Console.WriteLine(vec1.ToString());
            Console.WriteLine();


            //создание второго вектора
            Vector vec2 = new Vector(2, 1);
            Console.WriteLine("введите второй вектор:");
            for (Int32 j = 0; j < 1; j++)
            {
                for (Int32 i = 0; i < 2; i++)
                {
                    Console.Write("vec2[{0}, {1}] = ", i, j);
                    vec2[i, j] = Int32.Parse(Console.ReadLine());
                }
            }
            Console.WriteLine(vec2.ToString());
            Console.WriteLine();


            //перемножение двух векторов
            Console.WriteLine("произведение векторов {0}", vec1 * vec2);
            Console.WriteLine();


            //получение декримента векторов
            Console.WriteLine("декримент первого вектора {0: #.##}", (Double)vec1);
            Console.WriteLine("декримент второго вектора {0: #.##}", (Double)vec2);
            Console.WriteLine();


            //преобразование типов
            Int32[,] masVect = { {5}, {7} };
            Vector tempVect = masVect;
            Console.WriteLine(tempVect.ToString());
            Console.WriteLine();
            
            //создание элемента матрица
            Matrix mat = new Matrix(3, 3);
            Console.WriteLine("введите первую матрицу:");
            for (Int32 j = 0; j < 3; j++)
            {
                for (Int32 i = 0; i < 3; i++)
                {
                    Console.Write("mat[{0}, {1}] = ", i, j);
                    mat[i, j] = Int32.Parse(Console.ReadLine());
                }
            }
            Console.WriteLine();


            //Получение декримета матрицы
            Console.WriteLine("декримент матрицы {0}", (Double)mat);

            Console.ReadLine();
        }
    }
}
